package com.hubu.parking.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hubu.parking.entity.park.ParkingRecord;
import com.hubu.parking.entity.park.ParkingReservation;
import com.hubu.parking.entity.park.ParkingSpot;
import com.hubu.parking.entity.park.User;
import com.hubu.parking.mapper.ParkingRecordMapper;
import com.hubu.parking.model.dto.park.EndToSpotDto;
import com.hubu.parking.model.dto.park.PageListRecordRequest;
import com.hubu.parking.model.dto.park.StartToSpotDto;
import com.hubu.parking.model.enums.LogicStatusEnum;
import com.hubu.parking.model.enums.SpotStatusEnum;
import com.hubu.parking.model.vo.ParkingDurationVo;
import com.hubu.parking.model.vo.ParkingRecordVo;
import com.hubu.parking.service.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 19468
 * @description 针对表【parking_record(用户实际停车记录表)】的数据库操作Service实现
 * @createDate 2025-03-02 16:52:08
 */
@Service
public class ParkingRecordServiceImpl extends ServiceImpl<ParkingRecordMapper, ParkingRecord> implements ParkingRecordService {

    @Resource
    private ParkingSpotService spotService;

    @Resource
    private UserService userService;

    @Resource
    private ParkingReservationService reservationService;

    @Resource
    private SysConfigService configService;

    @Override
    public Page<ParkingRecordVo> pageListParkingRecord(PageListRecordRequest pageRequest) {
        // 1.分页参数
        Page<ParkingRecord> page = new Page<>();
        page.setCurrent(pageRequest.getCurrent());
        page.setSize(pageRequest.getPageSize());
        // 2.查询条件
        LambdaQueryWrapper<ParkingRecord> queryWrapper = new LambdaQueryWrapper<>();
        // 2.1 用户id
        Integer userId = pageRequest.getUserId();
        String userAccount = pageRequest.getUserAccount();
        String userName = pageRequest.getUserName();
        if (userId != null) {
            queryWrapper.eq(ParkingRecord::getUserId, userId);
        } else {
            // 账号和姓名不为空，则查询出符合的user列表，添加筛选条件
            if (StrUtil.isNotBlank(userAccount) || StrUtil.isNotBlank(userName)) {
                User user = new User();
                user.setUserAccount(userAccount);
                user.setUserName(userName);
                List<Integer> userIdsByCondition = userService.getUserIdsByCondition(user);
                if (!userIdsByCondition.isEmpty()) {
                    queryWrapper.in(ParkingRecord::getUserId, userIdsByCondition);
                }
            }
        }
        // 2.2 车位id
        Integer spotId = pageRequest.getSpotId();
        if (spotId != null) {
            queryWrapper.eq(ParkingRecord::getSpotId, spotId);
        }
        // 3.取出用户姓名和车位编号设置进去
        Page<ParkingRecord> sourcePage = this.page(page, queryWrapper);
        List<ParkingRecord> records = sourcePage.getRecords();
        ArrayList<ParkingRecordVo> parkingRecordVos = new ArrayList<>();
        for (ParkingRecord record : records) {
            ParkingRecordVo parkingRecordVo = new ParkingRecordVo();
            BeanUtil.copyProperties(record, parkingRecordVo);
            // 设置车位信息
            ParkingSpot spotById = spotService.getById(record.getSpotId());
            parkingRecordVo.setSpotNumber(spotById.getSpotNumber());
            parkingRecordVo.setLocation(spotById.getLocation());
            // 设置用户信息
            User userById = userService.getById(record.getUserId());
            parkingRecordVo.setUserName(userById.getUserName());
            parkingRecordVo.setUserAccount(userById.getUserAccount());
            // 设置完后，添加
            parkingRecordVos.add(parkingRecordVo);
        }
        // 4.重新填充records
        Page<ParkingRecordVo> resultPage = new Page<>();
        BeanUtil.copyProperties(sourcePage, resultPage);
        resultPage.setRecords(parkingRecordVos);
        return resultPage;
    }

    @Override
    public List<ParkingRecordVo> listRecordNoPage(PageListRecordRequest request) {
        // 校验
        if (request == null) {
            return null;
        }
        Integer userId = request.getUserId();
        if (userId == null) {
            return null;
        }
        // 查询该用户的记录
        LambdaQueryWrapper<ParkingRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParkingRecord::getUserId, userId);
        queryWrapper.orderByDesc(ParkingRecord::getStartTime);
        List<ParkingRecord> records = this.list(queryWrapper);
        // 填充数据
        List<ParkingRecordVo> parkingRecordVos = new ArrayList<>();
        for (ParkingRecord record : records) {
            ParkingRecordVo parkingRecordVo = new ParkingRecordVo();
            BeanUtil.copyProperties(record, parkingRecordVo);
            // 设置车位信息
            ParkingSpot spotById = spotService.getById(record.getSpotId());
            parkingRecordVo.setSpotNumber(spotById.getSpotNumber());
            parkingRecordVo.setLocation(spotById.getLocation());
            // 设置完后，添加
            parkingRecordVos.add(parkingRecordVo);
        }
        return parkingRecordVos;
    }

    @Override
    public ParkingDurationVo listDuration() {
        List<ParkingRecord> list = this.list();
        int[] count = new int[8];
        for (ParkingRecord parkingRecord : list) {
            long endTime = parkingRecord.getEndTime().getTime();
            long startTime = parkingRecord.getStartTime().getTime();
            int intervalIndex = getIntervalIndex(endTime, startTime);
            int temp = count[intervalIndex];
            count[intervalIndex] = temp + 1;
        }
        ParkingDurationVo parkingDurationVo = new ParkingDurationVo();
        String[] labels = {"0-1小时", "1-3小时", "3-6小时", "6-12小时", "12-24小时", "1-2天", "2-7天", "7天以上"};
        parkingDurationVo.setLabel(Arrays.stream(labels).collect(Collectors.toList()));
        parkingDurationVo.setCount(Arrays.stream(count).boxed().collect(Collectors.toList()));
        return parkingDurationVo;
    }

    @Override
    public void startToSpot(StartToSpotDto dto) {
        if (dto == null) {
            return;
        }
        Integer reservationId = dto.getReservationId();
        if (reservationId == null) {
            return;
        }
        // 修改预约状态
        ParkingReservation reservation = reservationService.getById(reservationId);
        reservation.setStatus(LogicStatusEnum.AVAILABLE.getValue());
        reservationService.updateById(reservation);
        // 插入记录表
        ParkingRecord parkingRecord = new ParkingRecord();
        parkingRecord.setReservationId(reservationId);
        parkingRecord.setSpotId(reservation.getSpotId());
        parkingRecord.setUserId(reservation.getUserId());
        parkingRecord.setEndTime(new Date());
        this.save(parkingRecord);
        // 修改车位状态
        Integer spotId = reservation.getSpotId();
        ParkingSpot spot = spotService.getById(spotId);
        spot.setStatus(SpotStatusEnum.PARKED.getValue());
        spotService.updateById(spot);
    }

    @Override
    public void endToSpot(EndToSpotDto dto) {
        if (dto == null) {
            return;
        }
        Integer recordId = dto.getRecordId();
        if (recordId == null) {
            return;
        }
        // 修改记录状态
        ParkingRecord record = this.getById(recordId);
        record.setStatus(LogicStatusEnum.AVAILABLE.getValue());
        this.updateById(record);
        // 修改车位状态
        Integer spotId = record.getSpotId();
        ParkingSpot spot = spotService.getById(spotId);
        spot.setStatus(SpotStatusEnum.AVAILABLE.getValue());
        spotService.updateById(spot);
    }

    @Override
    public List<ParkingRecord> listParingRecordNotEnd() {
        LambdaQueryWrapper<ParkingRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParkingRecord::getStatus, LogicStatusEnum.UN_AVAILABLE.getValue());
        return this.list(queryWrapper);
    }

    /**
     * 根据停车时长获取下标
     *
     * @param endTime   结束时间
     * @param startTime 开始时间
     * @return 下标
     */
    private int getIntervalIndex(long endTime, long startTime) {
        long parkTime = Math.abs(endTime - startTime);
        long oneHour = 1000 * 60 * 60;
        long per = parkTime / oneHour;
        int currentIndex = 0;
        if (per < 1) {
            return currentIndex;
        }
        currentIndex++;
        if (per < 3) {
            return currentIndex;
        }
        currentIndex++;
        if (per < 6) {
            return currentIndex;
        }
        currentIndex++;
        if (per < 12) {
            return currentIndex;
        }
        currentIndex++;
        if (per < 24) {
            return currentIndex;
        }
        currentIndex++;
        if (per < 48) {
            return currentIndex;
        }
        currentIndex++;
        if (per < 24 * 7) {
            return currentIndex;
        }
        currentIndex++;
        return currentIndex;
    }
}




